package com.sinodata.bsm.cicp.collector.weblogic9;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.Query;
import javax.management.QueryExp;
import javax.management.remote.JMXConnector;

import org.apache.log4j.Logger;

import com.sinodata.bsm.cicp.collector.Collector;
import com.sinodata.bsm.cicp.exception.CollectorException;
import com.sinodata.bsm.cicp.util.JmxUtil;
import com.sinodata.bsm.common.vo.ResPropertyValue;

/**
 * 
 * <p>
 * Description: 
 * </p>
 *
 * @author liulibo
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2012-12-26 AM 10:07:17   liulibo        1.0         To create
 * </p>
 *
 * @since 
 * @see
 */
public class WebApplicationCollector extends Collector {

    private static final Logger logger = Logger.getLogger(WebApplicationCollector.class);

    private final HashMap perSession = new HashMap();
    private final Set set = new HashSet();
    private long lastTime = -1;

    @Override
    public List<ResPropertyValue> collect(String ip) throws CollectorException {
        List<ResPropertyValue> values = new ArrayList<ResPropertyValue>();

        String[] propMetas = getPropMeta();
        ResPropertyValue propertyValueX = new ResPropertyValue();
        ResPropertyValue.PropValue[] propValues = new ResPropertyValue.PropValue[propMetas.length];

        String applicationName1 = this.getParamMap().get("AppName").trim();
        //        String contextRoot = this.getParamMap().get("ContextRoot").trim();
        String port = this.getParamMap().get("port").trim();
        String key = applicationName1 + ":" + ip;
        ObjectName service;
        String name = null;
        long servlets = 0;
        long openSessionsCurrentCount = 0;
        long openSessionsHighCount = 0;
        long sessionsOpenedTotalCount = 0;
        long time = System.currentTimeMillis();
        Object attrValues[] = null;
        JMXConnector connector = null;
        MBeanServerConnection connection = null;
        try {
            connector = JmxUtil.getConnection(ip, Integer.parseInt(port));
            connection = connector.getMBeanServerConnection();
            service = new ObjectName("com.bea:Name=DomainRuntimeService,Type=weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean");
            Object domainConfiguration = connection.getAttribute(service, "DomainConfiguration");
            ObjectName[] appDeployments = (ObjectName[]) connection.getAttribute((ObjectName) domainConfiguration, "AppDeployments");
            QueryExp typefilter = Query.match(Query.attr("Type"), Query.value("ApplicationRuntime"));
            QueryExp appfilter = null;
            if ((appDeployments != null) && (appDeployments.length > 0)) {
                for (ObjectName objectName : appDeployments) {
                    name = objectName.getKeyProperty("Name");
                    QueryExp tfilter = Query.match(Query.attr("ApplicationName"), Query.value(name));
                    if (appfilter == null) {
                        appfilter = tfilter;
                    } else {
                        appfilter = Query.or(appfilter, tfilter);
                    }
                }
                QueryExp destfilter = Query.and(typefilter, appfilter);
                long currentTimeMillis = System.currentTimeMillis();
                if (set.isEmpty() || currentTimeMillis > lastTime + 60 * 60 * 1000) {
                    set.clear();
                    Set test = connection.queryNames(new ObjectName("com.bea:*"), destfilter);
                    set.addAll(test);
                    lastTime = currentTimeMillis;
                }

                Iterator it = set.iterator();
                while (it.hasNext()) {
                    ObjectName objName = (ObjectName) it.next();
                    //                    String applicationName = objName.getKeyProperty("Name");
                    ObjectName[] componentRuntimes = (ObjectName[]) connection.getAttribute(objName, "ComponentRuntimes");
                    String attributeNames[] = new String[] { "Status", "SourceInfo", "Servlets", "OpenSessionsCurrentCount", "OpenSessionsHighCount", "SessionsOpenedTotalCount" };
                    for (ObjectName objectName2 : componentRuntimes) {
                        attrValues = JmxUtil.getAttribute(connection, objectName2, attributeNames);
                        propValues[0] = ResPropertyValue.createPropValue(attrValues[0].toString(), propMetas[0]);
                        propValues[1] = ResPropertyValue.createPropValue(attrValues[1].toString(), propMetas[1]);
                        ObjectName[] objNames = (ObjectName[]) attrValues[2];
                        servlets += objNames.length;
                        openSessionsCurrentCount += Integer.parseInt(attrValues[3].toString());
                        openSessionsHighCount = Integer.parseInt(attrValues[4].toString()) > openSessionsHighCount ? Integer.parseInt(attrValues[4].toString()) : openSessionsHighCount;
                        sessionsOpenedTotalCount += Integer.parseInt(attrValues[5].toString());

                    }
                }
            }
        } catch (Exception e) {
            logger.error("failed to collect by WebApplicationCollector", e);
            throw new CollectorException(e);
        } finally {
            JmxUtil.closeConnector(connector);
        }
        propValues[2] = ResPropertyValue.createPropValue(servlets + "", propMetas[2]);
        propValues[3] = ResPropertyValue.createPropValue(openSessionsCurrentCount + "", propMetas[3]);
        propValues[4] = ResPropertyValue.createPropValue(openSessionsHighCount + "", propMetas[4]);
        propValues[5] = ResPropertyValue.createPropValue(sessionsOpenedTotalCount + "", propMetas[5]);
        if (perSession.get(key) != null) {
            String temp = String.valueOf(perSession.get(key));
            String[] valueTime = temp.split(":");
            String resultString;
            if (Long.parseLong(attrValues[5].toString()) - Long.parseLong(valueTime[0]) < 0) {
                resultString = "0";
            } else {
                resultString = String.valueOf((Long.parseLong(attrValues[5].toString()) - Long.parseLong(valueTime[0])) * 1000 * 60 / (time - Long.parseLong(valueTime[1])));
            }
            propValues[6] = ResPropertyValue.createPropValue(resultString + "", propMetas[6]);
        }
        perSession.remove(key);
        perSession.put(key, attrValues[5].toString() + ":" + String.valueOf(time));
        propertyValueX.setValues(propValues);
        values.add(propertyValueX);
        return values;
    }

    @Override
    public String[] getParamMeta() {
        return new String[] { "AppName", "port" };
    }

    @Override
    public String[] getPropMeta() {
        //     return new String[] { "Status", "SourceInfo", "Servlets", "OpenSessionsCurrentCount", "OpenSessionsHighCount", "SessionsOpenedTotalCount", "SessionsOpenedPerMin" };
        return new String[] { "$1", "$2", "$3", "$4", "$5", "$6", "$7" };
    }

}